logo头像
Snippet 博客主题

swift - 快速设置富文本的分类

#一. range和NSRange互相转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
extension String {
/// range转换为NSRange
func nsRange(from range: Range<String.Index>) -> NSRange {
return NSRange(range, in: self)
}
//使用实例
// let languages = "Java,Swift,Objective-C"
// let one = "Swift"
// let range = languages.range(of: one)
// let nsRange = languages.nsRange(from: range!)
// print(nsRange) // {5, 5}

}

extension String {
/// NSRange转化为range
func range(from nsRange: NSRange) -> Range<String.Index>? {
guard
let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex),
let from = String.Index(from16, within: self),
let to = String.Index(to16, within: self)
else { return nil }
return from ..< to
}
}

二.NSMutableAttributedString快速添加属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
//
// NSMutableAttributedString+Extension.swift
// PXSSwift
//
// Created by 刘刘峰 on 2020/12/21.
// Copyright © 2020 刘刘峰. All rights reserved.
//

import Foundation
extension NSMutableAttributedString {
// =========================字体的设置=========================//
/// 设置字体大小
public func lf_addFont(_ font: UIFont, on range: NSRange) {

if self.length < range.location + range.length { return }

let attrs = [NSAttributedString.Key.font: font]
self.addAttributes(attrs, range: range)
}

/// 设置字体颜色
public func lf_addForegroundColor(_ color: UIColor, range: NSRange) {

if self.length < range.location + range.length {
return
}

let attrs = [NSAttributedString.Key.foregroundColor: color]
self.addAttributes(attrs, range: range)
}

/// 设置字体的背景颜色
public func lf_addBackgroundColor(_ color: UIColor, range: NSRange) {

if self.length < range.location + range.length {
return
}

let attrs = [NSAttributedString.Key.backgroundColor: color]
self.addAttributes(attrs, range: range)
}
}


extension NSMutableAttributedString {

//=========================文本的处理==========================//
/// 字符间距的设置 字符间距 正值间距加宽,负值间距变窄
public func lf_addKern(_ kern: Int, range: NSRange) {

if self.length < range.location + range.length { return }

let attrs = [NSAttributedString.Key.kern: kern]
self.addAttributes(attrs, range: range)
}


/// 设置字体倾斜度,正值右倾,负值左倾
public func lf_addObliqueness(_ obliqueness: CGFloat, range: NSRange) {

if self.length < range.location + range.length { return }

let attrs = [NSAttributedString.Key.obliqueness: obliqueness]
self.addAttributes(attrs, range: range)
}

/// 设置字体的横向拉伸,正值拉伸 ,负值压缩
public func lf_addExpansion(_ expansion: CGFloat, range: NSRange) {

if self.length < range.location + range.length { return }

let attrs = [NSAttributedString.Key.expansion: expansion]
self.addAttributes(attrs, range: range)
}

/// 文字书写方向
public func lf_addWritingDirection(_ direction: NSWritingDirection, range: NSRange) {

if self.length < range.location + range.length { return }


var value: (Int) = (0)


if direction == .leftToRight {
if #available(iOS 9.0, *) {
value = (NSWritingDirectionFormatType.override.rawValue | NSWritingDirection.leftToRight.rawValue)
} else {
// Fallback on earlier versions
}
} else {
if #available(iOS 9.0, *) {
value = (NSWritingDirectionFormatType.override.rawValue | NSWritingDirection.rightToLeft.rawValue)
} else {
// Fallback on earlier versions
}
}

/**
NSAttributedString.Key.writingDirection接收的是一个数组
*/

/**
//@[@(NSWritingDirectionLeftToRight | NSWritingDirectionEmbedding)]
//@[@(NSWritingDirectionLeftToRight | NSWritingDirectionOverride)]
//@[@(NSWritingDirectionRightToLeft | NSWritingDirectionEmbedding)]
//@[@(NSWritingDirectionRightToLeft | NSWritingDirectionOverride)]
// NSWritingDirectionOverride 和 NSWritingDirectionEmbedding 是指定Unicode双向定义的格式控制算法(具体的没太搞清楚)
*/

let attrs = [NSAttributedString.Key.writingDirection: [value]]
self.addAttributes(attrs, range: range)
}
}


extension NSMutableAttributedString {

//=========================删除线==========================//
/// 设置删除线 NSUnderlineStyle: none不设置,single单细线删除,thick粗单线, Double双细线
public func lf_addStrikethrough(style: NSUnderlineStyle = .single, color: UIColor? = nil, range: NSRange) {

if self.length < range.location + range.length {
return
}

let attr1 = [NSAttributedString.Key.strikethroughStyle: style.rawValue]
self.addAttributes(attr1, range: range)

if let tempColor = color {
let attr2 = [NSAttributedString.Key.strikethroughColor: tempColor]
self.addAttributes(attr2, range: range)
}
}


//=========================下划线==========================//
/// 设置下划线 NSUnderlineStyle: none不设置,single单细线删除,thick粗单线, Double双细线
public func lf_addUnderLine(style: NSUnderlineStyle = .single, color: UIColor? = nil, range: NSRange) {

if self.length < range.location + range.length {
return
}

let attrs = [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue]
self.addAttributes(attrs, range: range)

if let tempColor = color {
let attr2 = [NSAttributedString.Key.underlineColor: tempColor]
self.addAttributes(attr2, range: range)
}
}
}

extension NSMutableAttributedString {
//=========================文字的效果==========================//
/// 设置文字的描边
public func lf_addStroke(color: UIColor, width: CGFloat, range: NSRange) {

/**
设置文字描边颜色,需要NSStrokeWidthAttributeName设置描边宽度,这样就能使文字空心.

NSStrokeWidthAttributeName,该值改变笔画宽度(相对于字体 size 的百分比),负值填充效果,正值中空效果,默认为 0,即不改变。正数只改变描边宽度。负数同时改变文字的描边和填充宽度。例如,对于常见的空心字,这个值通常为 3.0。
同时设置了空心描边和文字前景两个属性,并且NSStrokeWidthAttributeName 属性设置为整数,文字前景色就无效果了
*/

if self.length < range.location + range.length { return }

let attrs = [
NSAttributedString.Key.strokeWidth: width,
NSAttributedString.Key.strokeColor: color
] as [NSAttributedString.Key : Any]
self.addAttributes(attrs, range: range)
}

/// 阴影
public func lf_addShadow(_ shadow: NSShadow, range: NSRange) {
if self.length < range.location + range.length { return }
let attrs = [NSAttributedString.Key.shadow: shadow]
self.addAttributes(attrs, range: range)
}

/// 设置文字的特殊NSAttributedString.Key这一个凸版印刷效果)
public func lf_addTextEffect(effect: NSAttributedString.TextEffectStyle = .letterpressStyle, range: NSRange) {
if self.length < range.location + range.length { return }
let attrs = [NSAttributedString.Key.textEffect: effect]
self.addAttributes(attrs, range: range)
}
}


extension NSMutableAttributedString {

//=========================偏移量==========================//
/// 设置上下偏移量 正数上移,负数下移
public func lf_addBaselineOffset(_ offset: CGFloat, range: NSRange) {
if self.length < range.location + range.length { return }
let attrs = [NSAttributedString.Key.baselineOffset: offset]
self.addAttributes(attrs, range: range)
}

/// 设置行间距
public func lf_addLineSpacing(_ style: NSMutableParagraphStyle, range: NSRange) {


/**
具体请看: https://www.jianshu.com/p/b0afc45bb642

NSAttributedString.Key.paragraphStyle 设置文本段落排版,为NSParagraphStyle对象

paragraphStyle.lineSpacing = 0.0; //增加行高
paragraphStyle.headIndent = 0; //头部缩进,相当于左padding
paragraphStyle.tailIndent = 0; //相当于右padding
paragraphStyle.lineHeightMultiple = 0; //行间距是多少倍
paragraphStyle.alignment = NSTextAlignmentLeft;//对齐方式
paragraphStyle.firstLineHeadIndent = 0; //首行头缩进
paragraphStyle.paragraphSpacing = 0; //段落后面的间距
paragraphStyle.paragraphSpacingBefore = 0; //段落之前的间距
*/

if self.length < range.location + range.length { return }

let attrs = [NSAttributedString.Key.paragraphStyle: style]
self.addAttributes(attrs, range: range)
}
}



extension NSMutableAttributedString {

/// 插入图片
public func lf_addTextAttachment(image: UIImage?, imageFrame: CGRect, atIndex index: Int) {

let attachment = NSTextAttachment.init()
attachment.image = image
attachment.bounds = imageFrame
let att = NSAttributedString(attachment: attachment)
self.insert(att, at: index)
}
}

三.项目中使用

1
2
3
4
5
6
let attr = NSMutableAttributedString.init(string: str)
let range = str.range(of: self.model?.view_rent_un_prefix ?? "")
let nsrange = str.nsRange(from: range!)

attr.lf_addForegroundColor(AppColor.themeColor, range: nsrange)
descLab.attributedText = attr
微信打赏

赞赏是不耍流氓的鼓励